#!/usr/bin/python3
# -*- coding:utf-8 -*-
# __author__ == taoyulong2018@gmail.com
# __time__ == 2023/8/17 13:59
# ===========================================
#       题目名称： 8. 字符串转换整数 (atoi)
#       题目地址： https://leetcode.cn/problems/string-to-integer-atoi/
#       题目描述： https://note.youdao.com/s/RRXNSXjR
# ===========================================


import math

"""
判断字符串是否为数字：
    isdigit()：如果字符串是数字字符串，返回True，否则返回False。(包含byte类型的数值)
    isnumeric()：如果字符串是数值字符串，返回True，否则返回False。 (包含中文壹、贰这种)
    isdecimal()：如果字符串是十进制字符串，返回True，否则返回False。

    isdigit()
    True: Unicode数字/全角数字（双字节）/byte数字（单字节）

    isnumeric()
    True: Unicode数字/全角数字（双字节）/汉字数字
        注意：字节数字时会报错

    isdecimal()
    True: Unicode数字/全角数字（双字节）
        注意：字节数字时会报错
"""


class Solution:
    """
        实现思路：
        定义stack 进行pop
    """

    def myAtoi(self, s):
        if not 0 <= len(s) <= 200:
            return 0
        symbol = None  # 符号
        stack = []  # 存放数值的地方
        symbols = ["+", "-", ".", " "]
        s = list(s)  # 将字符串转化为列表
        is_find_zero = False  # 前面是否找到0
        while s:
            head = s.pop(0)
            if head in symbols:
                if head in symbols[:2]:  # 前面符号
                    if stack or symbol or is_find_zero:
                        break
                    else:
                        symbol = head
                        continue

                if head == symbols[2] or symbol or ((is_find_zero or stack) and head == symbols[3]):
                    break
                if head == symbols[3]:
                    continue
            elif head.isdecimal():  # 数值
                if not stack and head == "0":
                    is_find_zero = True
                    continue
                stack.append(head)
            else:
                break

        if not stack:
            return 0
        if symbol:
            stack.insert(0, symbol)
        MAX_VALUE = int(math.pow(2, 31) - 1)  # 2的31次方
        MIN_VALUE = int(math.pow(-2, 31))  # -2的31次方
        val = int("".join(stack))
        if val > MAX_VALUE:
            val = MAX_VALUE
        if val < MIN_VALUE:
            val = MIN_VALUE
        return val

    def myAtoi3(self, s):
        val = 0
        if not 0 <= len(s) <= 200 or (len(s) == 1 and s in ("+", "-")):
            return val
        MAX_VALUE = int(math.pow(2, 31) - 1)  # 2的31次方
        MIN_VALUE = int(math.pow(-2, 31))  # -2的31次方
        s = list(s)
        stack = []
        front_find_zero = False
        while s:
            head = s.pop(0)
            if head.isalpha() \
                    or head == "." \
                    or (front_find_zero and head.isspace()) \
                    or (stack and head.isspace()) \
                    or (stack and stack[0] in ("+", "-") and head in ("+", "-")) \
                    or (stack and head in ("+", "-")):  # 发现字母
                break
            if head.isspace() or head.isalpha() or head == "0":
                if head == "0":
                    if stack:
                        stack.append(head)
                    front_find_zero = True
                continue
            if not front_find_zero or (front_find_zero and head.isdecimal()):
                stack.append(head)
                front_find_zero = False
            else:
                break
        if stack:
            if not (len(stack) == 1 and stack[0] in ("+", "-")):
                val = int("".join(stack))
                if val > MAX_VALUE:
                    val = MAX_VALUE
                if val < MIN_VALUE:
                    val = MIN_VALUE
        return val

    def myAtoi2(self, s):
        """
            错误
        """
        if not 0 <= len(s) <= 200:
            return 0
        MAX_VALUE = int(math.pow(2, 31) - 1)  # 2的31次方
        MIN_VALUE = int(math.pow(-2, 31))  # -2的31次方
        s = list(s)
        stack = []  # 存放数据的地方
        prefix_has_zero = False  # 前面有0
        while s:
            head = s.pop(0)
            if head in ("+", "-") and "+" not in stack and "-" not in stack:
                stack.append(head)
            elif head.isdecimal():  # 判断是否是十进制数值
                # 判断符号后面是否是0 -0
                if head == "0":
                    if not stack or stack[-1] in ("+", "-"):
                        continue
                stack.append(head)
            elif head.isspace() or head.isalpha():
                continue
            else:
                break
        cur_val = 0
        if stack:
            if not (len(stack) == 1 and stack[0] in ("+", "-")):
                cur_val = int("".join(stack))
                if cur_val < MIN_VALUE:
                    cur_val = MIN_VALUE
                if cur_val > MAX_VALUE:
                    cur_val = MAX_VALUE
        return cur_val


if __name__ == '__main__':
    s = Solution()
    # 42
    print("42 =>", s.myAtoi(s="42"))
    # -42
    print("-42 =>", s.myAtoi(s="   -42"))
    # 4193
    print("4193 =>", s.myAtoi(s="4193 with words"))
    # 32
    print("32 =>", s.myAtoi(s="0032"))
    # 0
    print("0 =>", s.myAtoi("words and 987"))
    # -2147483648
    print("-2147483648 =>", s.myAtoi("-91283472332"))
    # 0
    print("0 =>", s.myAtoi("+-12"))
    # 0
    print("0 =>", s.myAtoi("00000-42a1234"))
    # 3
    print("3 =>", s.myAtoi("3.14159"))
    # 0
    print("0 =>", s.myAtoi("+"))
    # 2147483647
    print("2147483647 =>", s.myAtoi("21474836460"))
    # 0
    print("0 =>", s.myAtoi("   +0 123"))
    # 0
    print("0 =>", s.myAtoi("-abc"))
    # -88827
    print("-88827 =>", s.myAtoi("    -88827   5655  U"))
    # -5
    print("-5 =>", s.myAtoi("-5-"))
    # -13
    print("-13 =>", s.myAtoi("-13+8"))
    # 0
    print("0 =>", s.myAtoi("+-12"))
    # 123
    print("123 =>", s.myAtoi("123-"))
    # 0
    print("0 =>", s.myAtoi(".1"))
    # 0
    print("0 =>", s.myAtoi("0  123"))
    # 123
    print("123 =>", s.myAtoi("123  456"))
